Skip to content

fix(mesh): authorize media-capture offers and guard unsolicited Claimed#189

Merged
mrjeeves merged 1 commit into
mainfrom
claude/dtls-sdp-mitm-analysis-0xxnlt
Jul 23, 2026
Merged

fix(mesh): authorize media-capture offers and guard unsolicited Claimed#189
mrjeeves merged 1 commit into
mainfrom
claude/dtls-sdp-mitm-analysis-0xxnlt

Conversation

@mrjeeves

Copy link
Copy Markdown
Owner

Summary

Closes two authorization gaps in the node engine (node/src/mesh.rs).

1. Unauthenticated media capture (screen / camera / mic)

route_drive_plane() classifies only terminal/files/sites routes, so the offer gate's authorized = route_drive_plane(route).is_none_or(...) was unconditionally true for Display / Video / Audio. An offer whose source endpoint is a capability on this machine makes this node capture its own screen/camera/microphone and stream it to the offerer — yet any authenticated peer's offer was auto-accepted, unlike input (gated per-frame) or terminal/files/sites (gated at admission). The only Display/Video screen was cec_screen_offer_denied, which is inert for a non-CEC peer.

Fix: add sender_may_source_media and screen the offer with it. A media-source offer this node would host is refused unless the sender is owner/fleet, a CEC technician holding a live ScreenView consent grant (screen kinds only), or a person this device extended an explicit share to that lets them consume that media on that capability — the same owner/fleet → CEC → share layering may_drive already uses, reusing the canonical Grant::permits so capability pinning is honoured. Legitimate flows (owner viewing a fleet member, a consented CEC technician, an explicit "Receive your screen" share) are unaffected. The receive/sink direction (a peer sharing their screen with me) is not gated — only offers that make this device source its own capture.

2. Unsolicited OwnershipControl::Claimed fleet takeover

The Claimed arm added its sender to this device's fleet member list and signed roster and handed it the fleet key, without ever checking this node had sent that peer a Claim — while the sibling arms (Release, FleetKey) each guard their sender. Both the member list and the roster are sources sender_may_control trusts, so any authenticated peer could send an unsolicited Claimed and gain full control (input, shell, disk, clipboard, sites).

Fix: record a pending-claim when claim() sends a Claim, and honour Claimed only from a peer in that set — consuming the entry on use, so a replayed or duplicate confirmation is ignored. Mirrors the per-sender guard the other ownership arms already apply.

Testing

  • cargo test -p allmystuff-node --no-default-features — compiles mesh.rs with both fixes and passes all 95 unit tests. (The host media libs — ALSA / x11-xcb / v4l — aren't available in this environment; the changes are media-type-agnostic and live in non-feature-gated code, so they compile identically under the default host build, which swaps only the capture backends.)

Notes

The CEC Support client consumes this engine by pinned release tag, so it picks up both fixes on the next allmystuff-node tag bump — no code change needed there.

🤖 Generated with Claude Code

https://claude.ai/code/session_01J3oMk6B7NDM2SeQZUSz2ku


Generated by Claude Code

@mrjeeves
mrjeeves force-pushed the claude/dtls-sdp-mitm-analysis-0xxnlt branch 2 times, most recently from 7f76aab to 3e6227e Compare July 23, 2026 16:55
Close two authorization gaps in the node engine.

Media-source offers were unauthenticated. route_drive_plane() classifies
only terminal/files/sites routes, so the offer gate's
`authorized = route_drive_plane(route).is_none_or(...)` was
unconditionally true for Display/Video/Audio. An offer whose source
endpoint is a capability on this machine makes this node capture its own
screen/camera/microphone and stream it to the offerer, yet any
authenticated peer's offer was auto-accepted — unlike input (gated per
frame) or terminal/files/sites (gated at admission). Add
sender_may_source_media and screen the offer with it: a media-source
offer this node would host is now refused unless the sender is
owner/fleet, a CEC technician holding a live ScreenView consent grant
(screen kinds only), or a person this device extended an explicit share
to that lets them consume that media on that capability — the same
owner/fleet -> CEC -> share layering may_drive already uses, reusing the
canonical Grant::permits so capability pinning is honoured.

Unsolicited OwnershipControl::Claimed took over the fleet. The Claimed
arm added its sender to this device's fleet member list and signed
roster and handed it the fleet key, without ever checking this node had
sent that peer a Claim — while the sibling arms (Release, FleetKey) each
guard their sender. Any authenticated peer could send an unsolicited
Claimed and gain full control (input, shell, disk, clipboard, sites).
Record a pending-claim when claim() sends a Claim, and honour Claimed
only from a peer in that set, consuming the entry on use so a replayed
or duplicate confirmation is ignored.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J3oMk6B7NDM2SeQZUSz2ku
@mrjeeves
mrjeeves force-pushed the claude/dtls-sdp-mitm-analysis-0xxnlt branch from 3e6227e to ee690f0 Compare July 23, 2026 18:00
@mrjeeves
mrjeeves merged commit 909fc43 into main Jul 23, 2026
24 of 25 checks passed
@mrjeeves
mrjeeves deleted the claude/dtls-sdp-mitm-analysis-0xxnlt branch July 23, 2026 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants